package config

import (
	"errors"
	"fmt"
	"strings"

	"github.com/dzwvip/oracle"
	"github.com/zeromicro/go-zero/zrpc"
	"gorm.io/driver/mysql"
	"gorm.io/driver/postgres"
	"gorm.io/driver/sqlserver"
	"gorm.io/gorm"
)

type (
	Config struct {
		zrpc.RpcServerConf
		Databases Databases
	}

	Databases struct {
		MainSource  string
		DataSources []DataSources
	}
	DataSources map[string]string
)

func (ds *Databases) ChoiceType() gorm.Dialector {
	var directory gorm.Dialector
	typ, source, _ := analysisDatabaseConnInfo(ds.MainSource, "::")
	switch strings.ToLower(typ) {
	case "mysql":
		directory = mysql.Open(source)
	// case "sqlite", "sqlite3":
	// 	directory = sqlite.Open(ds.DataSource)
	case "sqlserver":
		directory = sqlserver.Open(source)
	case "postgres":
		directory = postgres.Open(source)
	default:
		panic(fmt.Sprintf("Selected database type %s is not supported at the moment. Please modify.", typ))
	}
	return directory
}

func (ds *Databases) PrimaryDatabasesStatus() bool {
	return len(ds.MainSource) > 0
}

func (ds *Databases) MultipleDataSourcesStatus() bool {
	return len(ds.DataSources) > 0
}

func (ds *DataSources) ChoiceType() (name string, directory gorm.Dialector, err error) {
	if ds == nil {
		return "", nil, errors.New("未配置从库")
	}
	var typ, source string
	for key, value := range *ds {
		switch strings.ToLower(key) {
		case "name":
			name = value
		case "source":
			typ, source, err = analysisDatabaseConnInfo(value, "::")
			if err != nil {
				return
			}
		}
	}

	if name == "" || typ == "" || source == "" {
		err = errors.New("数据源缺少定义")
		return
	}
	switch strings.ToLower(typ) {
	case "mysql":
		directory = mysql.Open(source)
	// case "sqlite", "sqlite3":
	// 	directory = sqlite.Open(ds.DataSource)
	case "oracle":
		directory = oracle.Open(source)
	case "sqlserver":
		directory = sqlserver.Open(source)
	case "postgres":
		directory = postgres.Open(source)
	default:
		panic(fmt.Sprintf("Selected database type %s is not supported at the moment. Please modify.", typ))
	}
	return
}

func analysisDatabaseConnInfo(in, sep string) (typ, source string, err error) {
	parts := strings.Split(in, sep)
	if len(parts) != 2 {
		err = errors.New("数据源格式错误,正确格式为===> databaseType::connInfo")
		return
	}
	typ, source = parts[0], parts[1]
	return
}
